# Virtual Router Simulator 
#
# Copyright (C) 2009-2010 VRSim Project
# Author: Choonho Son <choonho@kt.com>
# URL: <http://vrsim.googlecode.com>
# For license information, see LICENSE.TXT
#

import VRSim.Globals as globals

from VRSim.Node.XML import XML
from VRSim.Node.GUIInfo import GUIInfo
from VRSim.Node.PhysNode import PhysNode
from VRSim.Node.Cisco_C7200 import Cisco_C7200
from VRSim.Node.Cisco_C3600 import Cisco_C3600
from VRSim.Node.Juniper_M40 import Juniper_M40
from VRSim.Node.DHCP import DHCP
from VRSim.Node.Linux import Linux

from VRSim.Node.WindowsXP import WindowsXP
from VRSim.Node.Domain import Domain
from VRSim.Node.CiscoDomain import CiscoDomain
from VRSim.Utils import message,  debug

from xml.dom.minidom import parse,  getDOMImplementation

class Node(XML):
    def __init__(self,  ptype,  normal_img,  selected_img):
        # XML
        XML.__init__(self,  "Node")
        
        # nodeid is global key for Node (PhysNode, GUIInfo)
        self.nodeid = globals.GApp.topology.node_baseid
        globals.GApp.topology.node_baseid += 1
        
        self.physnodeType = ptype
        self.physnode = None
        self.guiinfo = GUIInfo(normal_img,  selected_img)
        self.isVirtual = True
        
        # update member information
        self.initPhysNode()
        self.guiinfo.nodeid = self.nodeid
        self.physnode.nodeid = self.nodeid
        
        
        self.initNodeName()
        self.guiinfo.showHostname()
        
        
    def updateAll(self):
        # sync data (nodeid, node_name)
        self.updateNodeID()
        
    def updateNodeID(self):
        self.guiinfo.nodeid = self.nodeid
        self.physnode.nodeid = self.nodeid
       
    def initPhysNode(self):
        """ set Default Information for physical Node
        make PhysNode instance
        and update default VM name
        """
        # TODO if update Symbols
        if self.physnodeType == "Cisco C7200":
            self.physnode = Cisco_C7200(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("Dynamips")
        elif self.physnodeType == "Cisco C3600":
            self.physnode = Cisco_C3600(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("Dynamips")
        elif self.physnodeType ==  "Juniper M40":
            self.physnode = Juniper_M40(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("kvm")
        elif self.physnodeType == "Linux":
            self.physnode = Linux(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("kvm")
        elif self.physnodeType == "Windows XP":
            self.physnode = WindowsXP(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("kvm")
        else:
            """ Undefined Node
            """
            self.physnode = PhysNode(self.nodeid)
            self.vm = globals.GApp.topology.getVMName("kvm")
        
    def initNodeName(self):
        name = self.physnode.hostname
        self.physnode.hostname = name + "_" + str(self.nodeid)
        self.guiinfo.hostname = self.physnode.hostname
        
    # Change Node (virtual or real hardware)
    #
    def chEquipReal(self):
        if self.isVirtual == True:
            self.isVirtual = False
            globals.GApp.mainWindow.NodesSummary.refresh()
            return True
        else:
            message("Current Node is a real hardware")
            return False
    
    def chEquipVirtual(self):
        if self.isVirtual == False:
            self.isVirtual = True
            globals.GApp.mainWindow.NodesSummary.refresh()
            return True
        else:
            message("Current Node is a virtual hardware")
            return False
   

    def updateVM(self):
        # update Console port
        self.physnode.devices.console = globals.GApp.topology.getConsolePort(self.nodeid)
        
        # NodesSummary refresh needed
        globals.GApp.mainWindow.NodesSummary.refresh()
        
    # Node Operation
    # {Start, Stop, Suspend}
    def start(self):
        # vm name is needed
        return self.physnode.start(self.vm)
        
    def stop(self):
        return self.physnode.stop()
        
    def suspend(self):
        return self.physnode.suspend()
        
    # XML
    
    def getXML(self):
        # <Node name='RouterA'>
        # <type>Cisco 7200</type>
        # <vm>HyperA</vm>
        # <geoLocation X='123.3' Y='48.5'/>
        # <location X='123' Y='123'/>
        node = self.xml.createElement("Node")
        node.setAttribute("name",  self.physnode.hostname)
        type = self.xml.createElement("type")
        typeText = self.xml.createTextNode(self.physnodeType)
        type.appendChild(typeText)
        vm = self.xml.createElement("vm")
        vmText = self.xml.createTextNode(globals.GApp.topology.getVMType(self.vm))
        vm.appendChild(vmText)
        geolocation = self.xml.createElement("geoLocation")
        geolocation.setAttribute('X',  str(self.physnode.geoX))
        geolocation.setAttribute('Y',  str(self.physnode.geoY))
        location = self.xml.createElement("location")
        location.setAttribute('X',  str(self.physnode.posX))
        location.setAttribute('Y',  str(self.physnode.posY))
        #append
        node.appendChild(type)
        node.appendChild(vm)
        node.appendChild(geolocation)
        node.appendChild(location)
        
        # append domain information
        if self.isVirtual == True and isinstance(self.physnode,  Domain): 
            domain =  Domain.getXML(self.physnode)
            node.appendChild(domain)
        elif self.isVirtual == True and isinstance(self.physnode,  CiscoDomain):
            domain = CiscoDomain.getXML(self.physnode)
            node.appendChild(domain)
            
        return node
        
    def setXML(self,  node):
        debug("Called Node XML")
        # <Node name='RouterA'>                 self.physnode.hostname
        # <type>Cisco 7200</type>               self.physnodeType
        # <vm>HyperA</vm>                       self.vm
        # <geoLocation X='123.3' Y='48.5'/>     self.physnode.{geoX | geoY}     
        # <location X='123' Y='123'/>               self.physnode.{posX | posY}
        hostname = node.getAttribute("name")
        node_vm = node.getElementsByTagName("vm")[0]
        vmtype = node_vm.firstChild.data
        node_geoLocation = node.getElementsByTagName("geoLocation")[0]
        geoX = node_geoLocation.getAttribute("X")
        geoY = node_geoLocation.getAttribute("Y")
        node_location = node.getElementsByTagName("location")[0]
        locX = node_location.getAttribute("X")
        locY = node_location.getAttribute("Y")
        
        # update value
        self.physnode.hostname = hostname
        self.vm = globals.GApp.topology.getVMName(vmtype)
        self.physnode.geoX = geoX
        self.physnode.geoY = geoY
        self.physnode.posX = locX
        self.physnode.posY = locY
        
        # domain node
        domain = node.getElementsByTagName("domain")[0]
        self.physnode.setXML(domain)
        
        
        
        
